package xymt.novaway.system.aspect;

import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import xymt.novaway.common.core.domain.dto.RoleDTO;
import xymt.novaway.common.core.utils.StringUtils;
import xymt.novaway.common.satoken.utils.LoginHelper;
import xymt.novaway.system.annotation.DataScope;
import xymt.novaway.system.service.ISysDataScopeService;

import java.util.stream.Collectors;

/**
 * 数据权限过滤切面
 * 
 * @author NovaWay
 */
@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class DataScopeAspect {

    private final ISysDataScopeService dataScopeService;

    /**
     * 数据权限过滤切点
     */
    @Around("@annotation(dataScope)")
    public Object doAround(ProceedingJoinPoint point, DataScope dataScope) throws Throwable {
        try {
            clearDataScope(point);
            handleDataScope(point, dataScope);
            // 执行目标方法
            return point.proceed();
        } finally {
            // 清理ThreadLocal
            clearDataScope(point);
        }
    }

    /**
     * 处理数据权限
     */
    protected void handleDataScope(final JoinPoint joinPoint, DataScope dataScope) {
        try {
            // 获取当前用户
            Long userId = LoginHelper.getUserId();
            if (userId == null) {
                return;
            }

            // 获取用户角色列表
            java.util.List<Long> roleIds = new java.util.ArrayList<>();
            try {
                var loginUser = LoginHelper.getLoginUser();
                if (loginUser != null && CollUtil.isNotEmpty(loginUser.getRoles())) {
                    roleIds = loginUser.getRoles().stream()
                        .map(RoleDTO::getRoleId)
                        .collect(Collectors.toList());
                    log.debug("获取到用户角色列表: {}", roleIds);
                } else {
                    log.debug("用户未登录或无角色信息");
                }
            } catch (Exception e) {
                log.warn("获取用户角色列表失败", e);
                return;
            }
            
            if (CollUtil.isEmpty(roleIds)) {
                return;
            }

            // 启用高级字段权限时，根据permission动态查询所有相关字段配置
            if (dataScope.enableAdvancedFieldPermission() && StringUtils.isNotBlank(dataScope.permission())) {
                handleAdvancedFieldPermission(joinPoint, dataScope, roleIds);
            } else {
                // 处理传统数据权限（已弃用，仅保留兼容性）
                handleTraditionalDataScope(joinPoint, dataScope, userId);
            }

        } catch (Exception e) {
            log.error("数据权限处理异常", e);
        }
    }

    /**
     * 处理高级字段权限
     */
    private void handleAdvancedFieldPermission(JoinPoint joinPoint, DataScope dataScope, java.util.List<Long> roleIds) {
        StringBuilder sqlFilter = new StringBuilder();
        String permission = dataScope.permission();
        String methodName = joinPoint.getSignature().getName();
        
        log.info("=== AOP拦截到方法调用 ===");
        log.info("方法名: {}, 权限: {}, 角色IDs: {} (使用动态字段查询)", 
                  methodName, permission, roleIds);
        
        for (Long roleId : roleIds) {
            // 使用新的动态方法，根据permission自动查询所有相关字段配置
            String roleFilter = dataScopeService.getRoleDataScopeFilterByPermission(roleId, permission);
            if (StringUtils.isNotBlank(roleFilter)) {
                if (sqlFilter.length() > 0) {
                    sqlFilter.append(" OR ");
                }
                sqlFilter.append("(").append(roleFilter).append(")");
                log.info("角色{}的动态权限过滤条件: {}", roleId, roleFilter);
            } else {
                log.debug("角色{}在权限{}下无匹配的权限配置", roleId, permission);
            }
        }

        if (sqlFilter.length() > 0) {
            String tableAlias = StringUtils.isNotBlank(dataScope.tableAlias()) ? dataScope.tableAlias() + "." : "";
            String finalFilter = "(" + sqlFilter.toString() + ")";
            
            log.info("=== 生成SQL过滤条件 ===");
            log.info("最终过滤条件: {}", finalFilter);
            
            // 设置数据权限SQL
            setDataScopeSQL(joinPoint, finalFilter, tableAlias);
            
            log.info("=== SQL过滤条件已应用到查询 ===");
        } else {
            log.warn("=== 没有生成任何过滤条件 ===");
        }
    }

    /**
     * 处理传统数据权限（部门权限等）
     */
    private void handleTraditionalDataScope(JoinPoint joinPoint, DataScope dataScope, Long userId) {
        // 这里可以扩展传统的数据权限逻辑
        // 例如：部门权限、本人权限等
        log.debug("处理传统数据权限: permission={}, userId={}", dataScope.permission(), userId);
    }

    /**
     * 设置数据权限SQL（通过ThreadLocal传递）
     */
    private void setDataScopeSQL(JoinPoint joinPoint, String sqlFilter, String tableAlias) {
        // 获取permission作为标识
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        DataScope dataScope = signature.getMethod().getAnnotation(DataScope.class);
        String permission = dataScope != null ? dataScope.permission() : "unknown";
        
        // 将过滤条件存储到ThreadLocal
        DataScopeFilter.setDataScopeSQL(sqlFilter, permission);
        log.info("已将过滤条件存储到ThreadLocal: {}, 权限: {}", sqlFilter, permission);
    }

    /**
     * 清理数据权限
     */
    private void clearDataScope(JoinPoint joinPoint) {
        // 清理ThreadLocal中的数据权限条件
        DataScopeFilter.clearDataScopeSQL();
        log.debug("已清理ThreadLocal中的数据权限条件");
    }
}